/*
  This file is part of JCM.

  JCM is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  JCM is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with JCM.  If not, see <http://www.gnu.org/licenses/>.
*/
import java.awt.*;

/**
 * Classe responsável pela política do ciclo de foco num container.
*/
public class LightFocusTraversalPolicy extends FocusTraversalPolicy
{
  /** Array dos componentes do ciclo de foco na ordem de acesso. */
  private Component[] components;

  /** Índice do último componente adicionado ao array. */
  private int last;

  /**
   * Construtor da classe dimensionando o array com um número estimado
   * de componentes.
   *
   * @param capacity Dimensão inicial do array dos componentes.
  */
  public LightFocusTraversalPolicy(int capacity)
  {
    components = new Component[capacity];
    last = -1;
  }

  /**
   * Adiciona componente ao final do array.
   *
   * @param c Componente a adicionar.
  */
  public void add(Component c)
  {
    // checa a capacidade atual do array
    if (last+1 >= components.length)
    {
      // cria um array dimensionado com a capacidade incrementada
      Component[] aux = new Component[components.length + 10];
      // copia o conteúdo do array para o de maior capacidade
      System.arraycopy(components, 0, aux, 0, components.length);
      // aponta para o novo array
      components = aux;
    }
    components[++last] = c;
  }

  /**
   * Pesquisa componente no array de componentes do ciclo de foco.
   *
   * @param c Componente a pesquisar.
   * @return Índice do componente ou -1 se não encontrado.
  */
  private int indexOf(Component c)
  {
    for (int j=0; j <= last; j++)
    {
      if (components[j].equals(c)) return j;
    }
    return -1;
  }

  /**
   * Pesquisa componente posterior ao fornecido.
   *
   * @param c Componente a pesquisar.
   * @param r Container raiz do ciclo de foco (aka Focus Cycle Root).
   * @return Componente posterior ao fornecido.
  */
  public Component getComponentAfter(Container r, Component c)
  {
    return components[ (indexOf(c) + 1) % (last + 1) ];
  }

  /**
   * Pesquisa componente anterior ao fornecido.
   *
   * @param c Componente a pesquisar.
   * @param r Container raiz do ciclo de foco (aka Focus Cycle Root).
   * @return Componente anterior ao fornecido.
  */
  public Component getComponentBefore(Container r, Component c)
  {
    int ndx = indexOf(c);
    return components[ ndx == 0 ? last : ndx - 1 ];
  }

  /**
   * Pesquisa o componente default do ciclo de foco.
   *
   * @param r Container raiz do ciclo de foco (aka Focus Cycle Root).
   * @return Componente default do ciclo de foco.
  */
  public Component getDefaultComponent(Container r)
  {
    return components[0];
  }

  /**
   * Pesquisa o último componente do ciclo de foco.
   *
   * @param r Container raiz do ciclo de foco (aka Focus Cycle Root).
   * @return Último componente do ciclo de foco.
  */
  public Component getLastComponent(Container r)
  {
    return components[last];
  }

  /**
   * Pesquisa o primeiro componente do ciclo de foco.
   *
   * @param r Container raiz do ciclo de foco (aka Focus Cycle Root).
   * @return Primeiro componente do ciclo de foco.
  */
  public Component getFirstComponent(Container r)
  {
    return components[0];
  }
}
